<template>
  <div>
    <el-button v-if="showFastBtn" type="primary" @click="handleShiftChange('prev')">
      <i class="iconfont-sys iconsys-shang"></i>
      上班次</el-button
    >
    <el-popover ref="popover" trigger="click" width="auto" :hide-after="0">
      <template #reference>
        <el-button style="width: 220px"
          >{{ reactData.startTime }} {{ reactData.startShiftName }}
          <template v-if="showEndShift">
            －{{ reactData.endTime }} {{ reactData.endShiftName }}
          </template>
        </el-button>
      </template>

      <div style="width: 400px">
        <el-row>
          <el-col>
            <span>开始时间/班次: </span>

            <el-date-picker
              v-model="reactData.startTime"
              style="width: 150px"
              type="date"
              placeholder="请选择时间"
              value-format="YYYY-MM-DD"
              :clearable="false"
              :teleported="false"
              @change="handleChange"
            ></el-date-picker>

            <el-select-v2
              v-model="reactData.startShiftNum"
              style="width: 60px; margin-left: 8px"
              :teleported="false"
              :options="shiftOptions"
              @change="handleStartShiftChange"
            >
            </el-select-v2>
            <el-button
              v-if="!showEndShift"
              @click="handleConfirm"
              style="margin-left: 8px"
              type="primary"
              >确定</el-button
            >
          </el-col>
          <el-col style="margin-top: 8px" v-if="showEndShift">
            <span>结束时间/班次: </span>

            <el-date-picker
              v-model="reactData.endTime"
              style="width: 150px"
              type="date"
              placeholder="请选择时间"
              value-format="YYYY-MM-DD"
              :clearable="false"
              :teleported="false"
              @change="handleChange"
            ></el-date-picker>

            <el-select-v2
              v-model="reactData.endShiftNum"
              style="width: 60px; margin-left: 8px"
              :options="shiftOptions"
              :teleported="false"
              @change="handleEndShiftChange"
            >
            </el-select-v2>
            <el-button @click="handleConfirm" style="margin-left: 8px" type="primary"
              >确定</el-button
            >
          </el-col>
        </el-row>
      </div>
    </el-popover>

    <el-button
      v-if="showFastBtn"
      :disabled="getEndFastBtnDisabled"
      type="primary"
      @click="handleShiftChange('next')"
    >
      <i class="iconfont-sys iconsys-xia"></i>下班次</el-button
    >
  </div>
</template>

<script setup lang="ts">
  /**
   * 选择班次和时间
   */

  import { useDebounceFn } from '@vueuse/core'
  import { addDay, subDay, restoreTsId } from '@/utils'
  import { type Props, defaultProps } from './props'

  const props = withDefaults(defineProps<Props>(), defaultProps)

  const emits = defineEmits(['update:modelValue', 'confirm', 'change'])

  watch(
    () => props.modelValue,
    (val) => {
      setReactData(val)
    },
    { deep: true }
  )

  const popover = ref()

  const reactData = reactive({
    currTime: '',
    currShiftNum: '',
    startTime: '',
    startShiftNum: '',
    startShiftName: '',
    startTsId: '',
    endTime: '',
    endShiftNum: '',
    endShiftName: '',
    endTsId: ''
  })

  const setReactData = (data: any) => {
    Object.assign(reactData, data)
  }

  const getEndFastBtnDisabled = computed(() => {
    if (!props.showFastBtn) return true

    if (props.showEndShift) {
      // 有结束班次,用结束判断
      return (
        reactData.endTime === reactData.currTime && reactData.endShiftNum === reactData.currShiftNum
      )
    } else {
      // 没有结束班次,用开始判断
      return (
        reactData.startTime === reactData.currTime &&
        reactData.startShiftNum === reactData.currShiftNum
      )
    }
  })

  // 班次快捷切换
  const handleShiftChange = (direction: 'prev' | 'next') => {
    const { shiftOptions } = props
    if (!shiftOptions?.length) return

    const isPrev = direction === 'prev'

    // 获取当前班次索引
    const key = isPrev ? 'startShiftNum' : 'endShiftNum'
    const index = shiftOptions.findIndex((v) => v.value === reactData[key])

    // 边界处理
    const isEdge = isPrev ? index === 0 : index === shiftOptions.length - 1

    // 确定目标班次
    const item = isEdge
      ? // 已经是第一个或最后一个,重新循环
        shiftOptions[isPrev ? shiftOptions.length - 1 : 0]
      : // 取上一个或下一个
        shiftOptions[isPrev ? index - 1 : index + 1]

    // 日期调整
    if (isEdge) {
      const fn = isPrev ? subDay : addDay
      reactData.startTime && (reactData.startTime = fn(reactData.startTime, 1))
      props.showEndShift && reactData.endTime && (reactData.endTime = fn(reactData.endTime, 1))
    }

    if (item) {
      setReactData({
        startShiftNum: item.value,
        startShiftName: item.label,
        endShiftNum: item.value,
        endShiftName: item.label
      })
    }
    handleConfirm()
  }

  // 修改开始班次
  const handleStartShiftChange = (e) => {
    const item = props.shiftOptions.find((item) => item.value === e)
    if (item) {
      reactData.startShiftName = item.label
      reactData.startShiftNum = item.value
    }
    handleChange()
  }

  // 修改结束班次
  const handleEndShiftChange = (e) => {
    const item = props.shiftOptions.find((item) => item.value === e)
    if (item) {
      reactData.endShiftName = item.label
      reactData.endShiftNum = item.value
    }
    handleChange()
  }

  // 改变值 和确认区分开
  const handleChange = () => {
    debounceDispatchConfirm()
  }

  // 确定
  const handleConfirm = () => {
    debounceDispatchConfirm()
    popover.value.hide()
  }

  // 给事件添加一个防抖
  const debounceDispatchConfirm = useDebounceFn(() => {
    reactData.startTsId = restoreTsId(reactData.startTime, reactData.startShiftNum)
    props.showEndShift &&
      (reactData.endTsId = restoreTsId(reactData.endTime, reactData.endShiftNum))

    emits('confirm', reactData)
    emits('update:modelValue', reactData)
  }, 500)

  defineExpose({
    handleConfirm
  })
</script>

<style lang="scss" scoped>
  :deep(.el-select-dropdown__item) {
    padding: 0;
    text-align: center;
  }
</style>
